#include "kernel.h"

#define VESA_ENABLED 0

#define BOOT_STACK_SIZE  0x10000

PVOID BootStackLimit;
PVOID BootStackBase;

VOID ApEntry(VOID)
{
    KernelApEntry();

    SysHalt();
}

VOID KernelInitialize(VOID)

//++
//
//  Routine Description:
//
//    This function initializes the boot loader.
//
//--

{
    PBEB Beb;

    Beb = BlGetBeb();

    //
    // Check boot type and perform any necessary source specific initialization.
    //

    BlRtlPrintf("Booting from ");

    switch (Beb->BootType) {

        case BL_CD_BOOT: {

            BlRtlPrintf("CD in drive 0x%02x.\n\n", Beb->BootDriveNumber);

            BlCdInitialize((UINT8) Beb->BootDriveNumber);

            break;
        }

        case BL_FAT16_BOOT: {

            BlRtlPrintf("FAT16 on drive 0x%02x.\n\n", Beb->BootDriveNumber);

            BlFatInitialize((UINT8) Beb->BootDriveNumber, MBR_FAT16LBA);

            break;
        }

        case BL_FAT32_BOOT: {

            BlRtlPrintf("FAT32 on drive 0x%02x.\n\n", Beb->BootDriveNumber);

            BlFatInitialize((UINT8) Beb->BootDriveNumber, MBR_FAT32LBA);

            break;
        }

        case BL_PXE_BOOT: {

            BlRtlPrintf("network.\n");

            BlPxeInitialize();

            break;
        }

        case BL_FLASH_BOOT: {

            BlRtlPrintf("Flash.\n");

            BlFlashInitialize((PVOID)Beb->FlashImage, (PVOID)Beb->FlashImage);

            break;
        }

        default: {

            BlRtlPrintf("unknown source!\n");

            SysHalt();
        }
    }

    //
    // Initialize PNP BIOS support.
    //

    if (Beb->BootType != BL_FLASH_BOOT) {

        BlPnpInitialize();

    }

    //
    // Initialize MPS support.
    //

    BlMpsInitialize();

    //
    // Initialize ACPI support.
    //

    if (Beb->BootType != BL_FLASH_BOOT) {

        BlAcpiInitialize();

    }
    else {

        BlAcpiNumberOfProcessors = 1;

    }

    //
    // Set AP entry address.
    //

    Beb->ApEntry = (UINT32) (ULONG_PTR) KernelApEntry;

    //
    // Initialize Kernel.
    //

    if (BlCommandLine == NULL) 
	{

        BlCommandLine = L"";
    }

    KernelSetup(BlAcpiNumberOfProcessors,
                            &Beb->ApEntry16,
                            &Beb->ApStartupLock);
}

#define PLATFORM_STRING                 "x64"

BL_TIME BlStartTime;

VOID KernelEntry(VOID)

//++
//
//  Routine Description:
//
//    This function implements the non-legacy entry point for the boot loader.
//
//--

{
    PBEB Beb;

    Beb = BlGetBeb();

    //
    // Initialize the trap table.
    //
    BlTrapEnable();

    //
    // Initialize video.
    //

    BlVideoInitialize();

    //
    // Capture boot start time.
    //
    BlRtlGetCurrentTime(&BlStartTime);

    //
    // Initialize memory management (ring transitions must follow this call).
    //

    BlMmInitializeSystem();

    //
    // Initialize PCI support (probe for 1394 interfaces for KD).
    //
 
	BlPciInitialize();

    //
    // Initialize KD.
    //

    BlRtlPrintf("Looking for debugger.\n");
    BlKdInitialize();

    //
    // Print the welcome banner.
    //

    BlRtlPrintf("Boot Time: %02u/%02u/%02u %02u:%02u:%02u\n",
                BlStartTime.Month,
                BlStartTime.Day,
                BlStartTime.Year,
                BlStartTime.Hour,
                BlStartTime.Minute,
                BlStartTime.Second);

    //
    // Initialize VESA support.
    //

#if VESA_ENABLED

    BlVesaInitialize();

#endif

    //
    // Allocate and switch to the boot stack.
    //

    BootStackLimit = (PVOID) (ULONG_PTR) BlMmAllocatePhysicalRegion(BOOT_STACK_SIZE, BL_MM_PHYSICAL_REGION_BOOT_STACK);
    BootStackBase = (PVOID) ((ULONG_PTR) BootStackLimit + BOOT_STACK_SIZE);

    MmSwitchStack(BootStackBase, KernelInitialize);
}
